package hyl.base.flow;

import java.util.Map;
import com.alibaba.fastjson.JSONObject;

import hyl.base.flow.dao.HylFlowDao;
import hyl.base.flow.express.Depend;
import hyl.base.flow.express.Result;
import hyl.core.MyDate;
import hyl.core.MyFun;
import hyl.core.run.IDelegate;
import hyl.core.run.IDo;
import hyl.core.run.IFilter;

/**
 * 流flow 中的 工作环节
 */

public class Link {
	//private static final Logger logger = LoggerFactory.getLogger(Link.class);
	private String _name;
	// 前置器:负责过滤,预处理等,例如限制执行的角色,时间,只有满足条件才能执行单元
	public IFilter<Track> _frontFilter;
	// 后置器
	public IDo<Track> _AfterRun;
	// 中间件,执行部件
	public IDelegate<Track> _BeforeRun;
	// 依赖
	private Depend _depend = null;
	// 结果
	public Result _result = null;
	// 影响
	public Result _error = null;
	// 可重试次数
	protected Integer _Maxretry = 100;
	// 模型
	protected Flow _fm;


	/**
	 * 出错后是否回滚
	 */
	public Link(Flow fm, String name, String depends, Object result, Object error, Integer retry) {
		_fm = fm;
		_name = name;
		if (!MyFun.isEmpty(depends))
			_depend = Depend.getInstance(depends);
		if (result == null || (result instanceof String && ((String) result).isEmpty())
		    || (result instanceof JSONObject && ((JSONObject) result).isEmpty())) {
			_result = null;
			_error = new Result(error, Track.ERROR);
		} else {
			_result = new Result(result, Track.COMPLETE);
			if (error == null || (error instanceof String && ((String) error).isEmpty())
			    || (error instanceof JSONObject && ((JSONObject) error).isEmpty())) {
				_error = new Result(result, Track.ERROR);
			} else {
				_error = new Result(error, Track.ERROR);
			}
		}
		if (retry != null)
			_Maxretry = retry;
	}

	public String getName() {
		return _name;
	}

	public synchronized void run(Track flow) {
		run( flow,null);
	}
	public synchronized void run(Track flow,String 理由) {
		if (flow == null)
			return;
		int maxtms = _Maxretry;
		// 前置过滤
		if (_frontFilter != null) {
			if (!_frontFilter.where(flow))
				return;
		}
		// 如果依赖未完成放弃执行
		if (_depend != null && (!_depend.judge(flow)))
			return;
		while (maxtms > 0) { /** 重设可运行次数 */		
			HylFlowDao dao=	_fm._pf.getFlowDao();
			try {
				// 运行单元委托程序
				String sr = null;
				if (_BeforeRun != null) {
					sr = _BeforeRun.call(flow);// 根据运行结果处理状态
				}
				flow.setMarks(_result.getResult(sr));
				dao.updateTrack(flow,this,理由);
				break;
			} catch (Exception e) {
				flow.setMarks(_error.getResult(e.getMessage()));// 根据错误消息处理状态
				dao.appendErrors(flow,this,e);
			} 
			maxtms--;
			MyDate.sleep(100);
		}
		// 运行后置程序
		if (_AfterRun != null) {
			try {
				_AfterRun.run(flow);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	/**
	 * 用于查询明细记录时使用, 帮助快速生成sql的查询条件
	 * 用法: getWhere("a.",null)
	 * 可以 输出 where 表达式
	 * a.mdlname='xxxx流程' and substring(a.tracks,0,1)='2' and substring(a.tracks,1,1)='2'
	 */
	public String getWhere(String dbalias, String result) {
		StringBuilder sql = new StringBuilder();
		sql.append(dbalias).append("mdlname='").append(_fm._name).append("'");
		Map<String, Character> mp = _result.getResult(result);
		if (mp == null)
			return null;
		int n = mp.keySet().size();
		sql.append(" and ");
		if (n > 1)
			sql.append("concat( ");
		for (String st : mp.keySet()) {
			int i = _fm.getIndex(st) + 1;
			sql.append("substring(" + dbalias + "tracks," + i + ",1),");
		}
		sql.deleteCharAt(sql.length() - 1);
		if (n > 1)
			sql.append(" )");
		sql.append("='").append(MyFun.join(mp.values().toArray())).append("' ");
		return sql.toString();
	}

}
